/** 不能模块依赖 */

declare var browser: object
declare var chrome: object

/* global chrome: true,browser: true */
if (typeof browser === 'undefined') {
  browser = chrome
}

interface ReplaceExp {
  readonly pageTitle: RegExp
  readonly wrongLineBreak: RegExp
  readonly wrongIndent: RegExp
  readonly sectionPick: RegExp
  readonly imgPick: RegExp
  readonly modTime: RegExp
  readonly worngImgPick: RegExp
  readonly worngPPick: RegExp
  readonly metaPack: RegExp
}

interface TempStorgeObj {
  pageTitle?: string,
  pageLink?: string,
  allContentEle?: HTMLCollection,
  allContent: string[],
}

interface PackageStorgeObj {
  meta: Map<string, string>,
  imgList: string[],
  sectionList: string[],
  cover?: string,
  coverImg?: string,
  color: string[],
  colorImgs: string[],
  chatu: string[]
}

const replcaeExp: ReplaceExp = {
  /** 页面标题匹配 */
  pageTitle: /[\[【\(（].+?[\]】\)）]\s?/g,
  /** 异常断行匹配 */
  wrongLineBreak: /(\n)(\s){0,}(\n){1,}/g,
  /** 异常缩进匹配 */
  wrongIndent: /^\s*/mg,
  /** 段落匹配 */
  sectionPick: /(.*)\n/g,
  /** img元素匹配 */
  imgPick: /inori_img_([\d_]*?)_(\w{2,4})_inori/g,
  /** 错误img元素修正 */
  worngImgPick: /(<p>)(<img src='\/imgs\/inori_img_[\d_]+_inori.jpg' \/>\s{0,})/g,
  /** 空p元素修正 */
  worngPPick: /<p><\/p>/g,
  /** 多余修改时间匹配 */
  modTime: /本帖最后由.*\s编辑/,
  metaPack: /^(\W{2})[：:](.+)$/mg
}

let tempStorge: TempStorgeObj = {
  /** 页面链接 */
  pageLink: document.URL,
  /** 内容放置 */
  allContent: [],
  /** 页面标题 */
  pageTitle: '',
  /** 页面所有元素 */
  allContentEle: document.getElementsByClassName('t_f')
}

/** 页面预处理
 *
 * @param {String} url
 */
function preProcessing (url: string) {
  /** 页面是否适合处理 */
  if (url.match(/viewthread/) === null) throw new Error('请确认是否在正文页面或确认切换至“只看作者模式”')
  /** 去除编辑时间 */
  Array.from(tempStorge.allContentEle).forEach(function (e) {
    let i = e.firstElementChild
    if (i === null) {
      let num = document.getElementById(`postnum${e.id.match(/\d+/)}`).textContent
      console.warn(`出现异常楼层:${num}，该楼层可能并不是正文`)
    } else if (i.innerHTML.match(replcaeExp.modTime)) {
      e.removeChild(i)
    } else {
      let num = document.getElementById(`postnum${e.id.match(/\d+/)}`).textContent
      console.warn(`出现异常楼层:${num}，该楼层未找到楼层修改时间`)
    }
  })
  /** 添加制作按钮 */
  function appendElement () {
    let inoriButton: HTMLSpanElement = document.createElement('span')
    let inoriDiv: HTMLSpanElement = document.createElement('div')
    let inoriFrame: HTMLIFrameElement = document.createElement('iframe')
    let pageLink = browser.extension.getURL('pages/hello.html')

    let toptbz = document.getElementsByClassName('y')[0]
    inoriButton.innerText = '制作ePub'
    inoriButton.style.width = '4em'
    inoriButton.style.padding = '0 14px'
    inoriButton.style.height = '28px'
    inoriButton.style.cursor = 'pointer'
    inoriButton.addEventListener('click', async () => {
      inoriDiv.style.height = '3em'
      inoriFrame.style.height = '3em'
      browser.runtime.onConnect.addListener((port: any) => {
        if (port.name === 'BGAllDone') {
          inoriDiv.style.height = '50vh'
          inoriDiv.style.minHeight = '300px'
          inoriFrame.style.height = '50vh'
          inoriFrame.style.minHeight = '300px'
        }
      })
      await main()
    })
    toptbz.appendChild(inoriButton)

    inoriFrame.src = pageLink
    inoriFrame.id = 'inori_frame'
    inoriFrame.style.display = 'block'
    inoriFrame.style.position = 'fixed'
    inoriFrame.style.top = '0'
    inoriFrame.style.left = '0'
    inoriFrame.style.width = '100%'
    inoriFrame.style.height = '0'
    document.body.appendChild(inoriFrame)

    inoriDiv.style.height = '0'
    document.body.insertBefore(inoriDiv, document.body.firstChild)
  }
  appendElement()
  console.log('inori: 准备完毕，可以执行制作')
}

/** 辅助函数：传送给bg处理
 * @param type 'fetch' | 'storage'
 * @param message JSON
 */
async function sendToBakcground (type: string, message: Array<string>) {
  if (type !== undefined && type === 'fetch') {
    let fetchPort = browser.runtime.connect({name: 'fetch'})
    fetchPort.postMessage(message)
    return new Promise ((res, rej) => {
      fetchPort.onMessage.addListener((msg: string[]) => {
        res(msg[1])
      })
    })
  } else if (type !== undefined && type === 'storage') {
    let storagePort = browser.runtime.connect({name: 'storage'})
    storagePort.postMessage(message)
  } else {
    console.error(`sendToBakcground执行失败，遇到未知指令：\n{type:${type}, message:${message}}`)
  }
}

/** 页面整体处理
 * 目标：得到图片储存以及处理后文字
 */
async function pageProcessing () {
  let index: number = 1
  async function imgProcessing (imgCloneList: NodeListOf<HTMLImageElement>) {
    let i: number = 1
    for (let img of Array.from(imgCloneList)) {
      let t = img.getAttribute('file') || null // 轻国自带表情的图片是最简单的img标签，只有src
      if (t !== null) {
        // 不是轻国表情
        t = t.replace(/^(?![(www\.)(http)])(\w+)/, 'https://www.lightnovel.cn/$1')
        let id = img.id
        let tempArray: Array<string> = [`${index}_${i}`, t]
        let suf: string = await sendToBakcground('fetch', tempArray) as string | null
        document.getElementById(id).outerHTML = `inori_img_${index}_${i}_${suf}_inori`
        i++
      }
    }
  }
  async function lcProcessing (ele: Element) {
    /** clone后的楼层，仅供元素获取，内容因为不能连接到css所以会错位 */
    let cloneEle: HTMLElement = ele.cloneNode(true)
    tempStorge.allContent = []
    /** 临时变量数组，用于储存图片地址 */
    let tempImg: string[] = []
    /** 图片缓存数列 */
    let imgList = ele.getElementsByTagName('img')
    /** clone图片数列，不变 */
    const imgCloneList = cloneEle.getElementsByTagName('img')
    /** 处理图片地址 直接替换图片标签并发送bg */
    await imgProcessing(imgCloneList)
    /** 处理正文 */
    let final = ele.outerText.replace(replcaeExp.wrongLineBreak, '$1')
      .replace(replcaeExp.wrongIndent, '')
      .replace(replcaeExp.modTime, '')
      .replace(replcaeExp.sectionPick, '<p>$1</p>\n')
      .replace(replcaeExp.imgPick, `<img src='../imgs/$1.$2' />`)
      .replace(replcaeExp.worngImgPick, `$2$1`)
      .replace(replcaeExp.worngPPick, '')
      .replace(/\n/mg, '')
    ele.innerHTML = ele.innerHTML.replace(replcaeExp.imgPick, `<img src='../imgs/$1.$2' />`)
    let tempMap: string[] = [`${index}楼`,`${final}`]
    await sendToBakcground('storage', tempMap)
    index++
  }
  for (let ele of Array.from(tempStorge.allContentEle)) {
    await lcProcessing(ele)
  }
  browser.runtime.connect({name: 'allDone'})
}

/** 主函数
 * 由制作按钮触发
 */
async function main () {
  browser.runtime.connect({name: 'fontEnd ready'})
  await pageProcessing()
}
preProcessing(tempStorge.pageLink)

/** 测试getUrl代码段
 * let testLink = document.createElement('a')
 * testLink.href = browser.extension.getURL('index.html')
 * testLink.innerText = 'inori_test'
 * document.body.appendChild(testLink)
 */
